﻿using System.Collections.Generic;

namespace SharpTag.ID3
{
    /// <summary>
    /// Represents the different types of <see cref="IFrame"/> data delimiters.
    /// </summary>
    public enum FrameDelimiter
    {
        /// <summary>
        /// Frame data field is One Byte in length.
        /// </summary>
        OneByte,
        /// <summary>
        /// Frame data field is Two Bytes in length.
        /// </summary>
        TwoBytes,
        /// <summary>
        /// Frame data field is Three Bytes in length.
        /// </summary>
        ThreeBytes,
        /// <summary>
        /// Frame data field is Four Bytes in length.
        /// </summary>
        FourBytes,
        /// <summary>
        /// Frame data field is null-terminated.
        /// </summary>
        ZeroedByte,
        /// <summary>
        /// Frame data field is a null-terminated string.
        /// </summary>
        ZeroedByteString,
        /// <summary>
        /// Frame data field goes to the end of the frame.
        /// </summary>
        EndOfFrame,
        /// <summary>
        /// Frame data field is a string that goes to the end of the frame.
        /// </summary>
        EndOfFrameString
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for Text frames.
    /// </summary>
    public class TextFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "TextEncoding", FrameDelimiter.OneByte },
            { "Information", FrameDelimiter.EndOfFrameString }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "Information"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for URL frames.
    /// </summary>
    public class URLFrameDefinitions : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "URL", FrameDelimiter.EndOfFrameString }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "URL"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for UFID frames.
    /// </summary>
    public class UFIDFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "OwnerIdentifier", FrameDelimiter.ZeroedByte },
            { "Identifier", FrameDelimiter.EndOfFrame }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "Identifier"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for IPLS frames.
    /// </summary>
    public class IPLSFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "TextEncoding", FrameDelimiter.OneByte },
            { "PeopleList", FrameDelimiter.EndOfFrameString }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "PeopleList"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for MCDI frames.
    /// </summary>
    public class MCDIFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "CDTOC", FrameDelimiter.EndOfFrame }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "CDTOC"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for ETCO frames.
    /// </summary>
    public class ETCOFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            //TODO: Define the ETCO Frame format
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return null; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for MLLT frames.
    /// </summary>
    public class MLLTFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "MPEGFramesBetweenReference", FrameDelimiter.TwoBytes },
            { "BytesBetweenReference", FrameDelimiter.ThreeBytes },
            { "MillisecondsBetweenReference", FrameDelimiter.ThreeBytes },
            { "BitsForBytesDeviation", FrameDelimiter.OneByte },
            { "BitsForMillisecondsDeviation", FrameDelimiter.OneByte }
            // TODO: Finish definition of the MLLT Frame format
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "MPEGFramesBetweenReference"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for SYTC frames.
    /// </summary>
    public class SYTCFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "TimeStampFormat", FrameDelimiter.OneByte },
            { "TempoData", FrameDelimiter.EndOfFrame }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "TempoData"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for USLT frames.
    /// </summary>
    public class USLTFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "TextEncoding", FrameDelimiter.OneByte },
            { "Language", FrameDelimiter.ThreeBytes },
            { "ContentDescriptor", FrameDelimiter.ZeroedByteString },
            { "Text", FrameDelimiter.EndOfFrameString }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "Text"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for SYLT frames.
    /// </summary>
    public class SYLTFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "TextEncoding", FrameDelimiter.OneByte },
            { "Language", FrameDelimiter.ThreeBytes },
            { "TimeStampFormat", FrameDelimiter.OneByte },
            { "ContentType", FrameDelimiter.OneByte },
            { "ContentDescriptor", FrameDelimiter.ZeroedByteString }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "ContentDescriptor"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for COMM frames.
    /// </summary>
    public class COMMFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string,FrameDelimiter>()
        {
            { "TextEncoding", FrameDelimiter.OneByte },
            { "Language", FrameDelimiter.ThreeBytes },
            { "ShortContentDescription", FrameDelimiter.ZeroedByteString },
            { "Text", FrameDelimiter.EndOfFrameString }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "Text"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for RVAD frames.
    /// </summary>
    public class RVADFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            //TODO: Define the RVAD Frame format
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return null; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for RVRB frames.
    /// </summary>
    public class RVRBFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            //TODO: Define the RVRB Frame format
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return null; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for APIC frames.
    /// </summary>
    public class APICFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            //TODO: Define the APIC Frame format
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return null; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for GEOB frames.
    /// </summary>
    public class GEOBFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "TextEncoding", FrameDelimiter.OneByte },
            { "MIMEType", FrameDelimiter.ZeroedByteString },
            { "Filename", FrameDelimiter.ZeroedByteString },
            { "ContentDescription", FrameDelimiter.ZeroedByteString },
            { "EncapsolatedObject", FrameDelimiter.EndOfFrame }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "ContentDescription"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for PCNT frames.
    /// </summary>
    public class PCNTFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "Counter", FrameDelimiter.FourBytes }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "Counter"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for POPM frames.
    /// </summary>
    public class POPMFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "EmailToUser", FrameDelimiter.ZeroedByteString },
            { "Rating", FrameDelimiter.OneByte },
            { "Counter", FrameDelimiter.FourBytes }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "Rating"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for RBUF frames.
    /// </summary>
    public class RBUFFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "BufferSize", FrameDelimiter.ThreeBytes },
            { "EmbeddedInfoFlag", FrameDelimiter.OneByte },
            { "OffsetToNextFlag", FrameDelimiter.FourBytes }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "BufferSize"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for AENC frames.
    /// </summary>
    public class AENCFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "OwnerIdentifier", FrameDelimiter.ZeroedByteString },
            { "PreviewStart", FrameDelimiter.TwoBytes },
            { "PreviewLength", FrameDelimiter.TwoBytes },
            { "EncryptionInfo", FrameDelimiter.EndOfFrame }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "EncryptionInfo"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for LINK frames.
    /// </summary>
    public class LINKFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "FrameIdentifier", FrameDelimiter.ThreeBytes },
            { "URL", FrameDelimiter.ZeroedByteString },
            { "AdditionalData", FrameDelimiter.EndOfFrameString }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "URL"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for POSS frames.
    /// </summary>
    public class POSSFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "TimeStampFormat", FrameDelimiter.OneByte },
            { "Position", FrameDelimiter.EndOfFrame }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "Position"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for USER frames.
    /// </summary>
    public class USERFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "TextEncoding", FrameDelimiter.OneByte },
            { "Language", FrameDelimiter.ThreeBytes },
            { "Text", FrameDelimiter.EndOfFrameString }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "Text"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for OWNE frames.
    /// </summary>
    public class OWNEFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "TextEncoding", FrameDelimiter.OneByte },
            { "PricePayed", FrameDelimiter.ZeroedByteString },
            { "DateOfPurchase", FrameDelimiter.ZeroedByteString },
            { "Seller", FrameDelimiter.EndOfFrameString }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "Seller"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for COMR frames.
    /// </summary>
    public class COMRFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "TextEncoding", FrameDelimiter.OneByte },
            { "PriceString", FrameDelimiter.ZeroedByteString },
            { "Validuntil", FrameDelimiter.ZeroedByteString },
            { "ContactURL", FrameDelimiter.ZeroedByteString },
            { "ReceivedAs", FrameDelimiter.OneByte },
            { "NameOfSeller", FrameDelimiter.ZeroedByteString },
            { "Description", FrameDelimiter.ZeroedByteString },
            { "PictureMIMEType", FrameDelimiter.ZeroedByteString },
            { "SellerLogo", FrameDelimiter.EndOfFrame }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "Description"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for ENCR frames.
    /// </summary>
    public class ENCRFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "OwnerIdentifier", FrameDelimiter.ZeroedByteString },
            { "MethodSymbol", FrameDelimiter.OneByte },
            { "EncryptionData", FrameDelimiter.EndOfFrame }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "EncryptionData"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for GRID frames.
    /// </summary>
    public class GRIDFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "OwnerIdentifier", FrameDelimiter.ZeroedByteString },
            { "GroupSymbol", FrameDelimiter.OneByte },
            { "GroupDependentData", FrameDelimiter.EndOfFrame }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "GroupSymbol"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for PRIV frames.
    /// </summary>
    public class PRIVFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "OwnerIdentifier", FrameDelimiter.ZeroedByteString },
            { "PrivateData", FrameDelimiter.EndOfFrame }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "PrivateData"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for ASPI frames.
    /// </summary>
    public class ASPIFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "IndexedDataStart", FrameDelimiter.FourBytes },
            { "IndexedDataLength", FrameDelimiter.FourBytes },
            { "NumberOfIndexPoints", FrameDelimiter.TwoBytes },
            { "BitsPerIndexPoint", FrameDelimiter.OneByte }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "IndexedDataStart"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for EQU2 frames.
    /// </summary>
    public class EQU2FrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "InterpolationMethod", FrameDelimiter.OneByte },
            { "Identification", FrameDelimiter.ZeroedByteString }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "Identification"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for RVA2 frames.
    /// </summary>
    public class RVA2FrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "Identification", FrameDelimiter.ZeroedByteString }
            // TODO: Finish RVA2 FrameDefinition
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "Identification"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for SEEK frames.
    /// </summary>
    public class SEEKFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "MinimumOffsetToNextTag", FrameDelimiter.FourBytes }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "MinimumOffsetToNextTag"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    /// <summary>
    /// Contains the <see cref="IFrameDefinition"/> information for SIGN frames.
    /// </summary>
    public class SIGNFrameDefinition : IFrameDefinition
    {
        Dictionary<string, FrameDelimiter> frameDelimiters = new Dictionary<string, FrameDelimiter>()
        {
            { "GroupSymbol", FrameDelimiter.OneByte },
            { "Signature", FrameDelimiter.EndOfFrame }
        };

        /// <summary>
        /// The Primary Key to use when extracting the main data from a Frame data field.
        /// </summary>
        public string PrimaryKey
        {
            get { return "Signature"; }
        }

        /// <summary>
        /// Gets the Dictionary containing the delimiters for the frame.
        /// </summary>
        public Dictionary<string, FrameDelimiter> FrameDelimiters
        {
            get { return frameDelimiters; }
        }
    }

    //TODO: Add any missed frames from Tags with versions less than 2.4
}